package com.hemerasolutions.v2trainer.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.stereotype.Repository;

import com.hemerasolutions.v2trainer.dao.interfaces.TrainingDaoInterface;
import com.hemerasolutions.v2trainer.model.exercise.Exercise;
import com.hemerasolutions.v2trainer.model.exercise.Exercise_;
import com.hemerasolutions.v2trainer.model.library.Library;
import com.hemerasolutions.v2trainer.model.modality.Modality;
import com.hemerasolutions.v2trainer.model.training.Training;
import com.hemerasolutions.v2trainer.model.training.TrainingStep;
import com.hemerasolutions.v2trainer.model.training.TrainingStep_;
import com.hemerasolutions.v2trainer.model.training.Training_;
import com.hemerasolutions.v2trainer.model.training.VersionableTraining;
import com.hemerasolutions.v2trainer.model.training.VersionableTraining_;
import com.hemerasolutions.v2trainer.model.training.statistic.TrainingStatistic;
import com.hemerasolutions.v2trainer.model.training.statistic.TrainingStatistic_;

@Repository(value = "trainingDao")
public class TrainingDao extends BaseDao<Training> implements TrainingDaoInterface {

	private static final long serialVersionUID = 1L;

	@Override
	public List<Training> search(Map<String, Object> fields) {
		// TODO Auto-generated method stub
		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Training> searchTraining(Map<String, Object> fields) {
		List<Predicate> predicateList = new ArrayList<Predicate>();

		CriteriaBuilder cb = this.getEntityManager().getCriteriaBuilder();

		CriteriaQuery<Training> cq  = cb.createQuery(Training.class);
		
		Root<Training> training = cq.from(Training.class);

		Join<Training,TrainingStep> trainingSteps = null;
		
		Join<TrainingStep,TrainingStatistic> trainingStatistics = null;
		
		
		Predicate pred;
		
	    for (Map.Entry<String,Object> line : fields.entrySet()) {
	    	
	    	
	    	if( line.getKey().toString() == "name"){
	    		pred = cb.like(cb.upper(training.get(Training_.name)), "%"+line.getValue().toString().toUpperCase()+"%");
	    		predicateList.add(pred);    
	    		
	    	}else if (line.getKey().toString() == "description"){
	    		pred = cb.like(cb.upper(training.get(Training_.description)), "%"+line.getValue().toString().toUpperCase()+"%");
	    		predicateList.add(pred);    
	    		
	    	}else if (line.getKey().toString() == "obs"){
	    		pred = cb.like(cb.upper(training.get(Training_.obs)), "%"+line.getValue().toString().toUpperCase()+"%");
	    		predicateList.add(pred);    

	    	}else if( line.getKey().toString() == "begChangedAt" ){ 
	    		pred = cb.greaterThanOrEqualTo(training.get(Training_.lastChange), this.begDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		

	    	}else if( line.getKey().toString() == "endChangedAt" ){ 
	    		pred = cb.lessThanOrEqualTo(training.get(Training_.lastChange), this.endDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	
	    	}else if( line.getKey().toString() == "begCreatedAt" ){ 
	    		pred = cb.greaterThanOrEqualTo(training.get(Training_.createdAt), this.begDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		
	    	
	    	}else if( line.getKey().toString() == "endCreatedAt" ){ 
	    		pred = cb.lessThanOrEqualTo(training.get(Training_.createdAt), this.endDayDateHour((Date)line.getValue()));
	    		predicateList.add(pred);    		

	    	}else if( line.getKey().toString() == "trainingSystem" ){ 
	    		pred = cb.equal(training.get(Training_.trainingSystem), line.getValue());
	    		predicateList.add(pred);    		

	    	}else if( line.getKey().toString() == "modalitys" ){ 

	    		if( trainingSteps == null){
	    			trainingSteps = training.join(Training_.trainingSteps);
	    		}
	    		
	    		if(trainingStatistics == null){
	    			trainingStatistics = trainingSteps.join(TrainingStep_.trainingStatistics);
	    		}
	    		
	    		
	    		List<Modality> modalitys = (List<Modality>) line.getValue();
	    		Path<Exercise> exercise  = trainingStatistics.get(TrainingStatistic_.exercise);

	    		Expression<Modality> mod =  exercise.get(Exercise_.modality);
	    		
	    		pred = mod.in(modalitys);
	    		predicateList.add(pred);    		

	    	}else if( line.getKey().toString() == "trainingTypes" ){ 
	    		pred = cb.equal(training.get(Training_.trainingSystem), line.getValue());
	    		predicateList.add(pred);    		

	    	}else if( line.getKey().toString() == "librarys" ){
	    		
	    		Path<VersionableTraining> vt = training.get(Training_.versionableTraining);
	    		Expression<Library> lib =  vt.get(VersionableTraining_.library);
	    		
	    		pred = lib.in((List<Library>)line.getValue());
	    		predicateList.add(pred);    		

	    	}
    	
	    }
	    
	    Predicate[] predicates = new Predicate[predicateList.size()];
	    predicateList.toArray(predicates);
	    cq.where(predicates);
	 
	    
	    return super.getEntityManager().createQuery(cq).getResultList();	
	}

}
